<?php

/**
 * 安心站长axzz.cn，一个追求技术创造者。让网站、小程序、APP牛起来……
 *
 * cighsen02 365182575
 * 
 * Create at: 2025.08.23
 * Update at: 2025.09.02
*/

namespace Twoir\Service\ShowKey;

use Exception;
use InvalidArgumentException;

use function base64_encode;
use function ecmsSetShowKey;
use function function_exists;
use function imagecolorallocate;
use function imagecreate;
use function imagedestroy;
use function imagefill;
use function imagegif;
use function imagejpeg;
use function imagepng;
use function imagettfbbox;
use function imagesetpixel;
use function imagettftext;
use function imagewbmp;
use function mt_rand;
use function rand;
use function sprintf;

/**
 * 回答问题验证码
 */
class QaImage extends BaseImage implements OutputInterface
{
    public function __construct($imageType = 'jpeg', $width = 60, $height = 24, $fontsize = 16){
        
        parent::__construct($imageType, $width, $height, $fontsize);
    }

    /**
     * 验证码渲染
     *
     * @param array $add
     * @return string
     *
     * @throws Exception
     */
    public function render(array $add): string
    {
        return $this->base64DataURI($add, false);
    }

    /**
     * 生成图像
     *
     * @param array $add
     * @param bool $imageBase64
     * @return string
     * 
     * @throws Exception
     */
    public function base64DataURI(array $add, bool $imageBase64 = true): string
    {
        if (empty($add) || !isset($add['v']) || empty($add['v'])) throw new Exception('参数错误', 9200);

        if (!array_key_exists($add['v'], static::VERIFY_KEY)) throw new Exception('无效' . $add['v'], 9200);

        [$question, $answer] = $this->randomQuestionAndAnswer();;

        if(is_bool($imageData = $this->imageData($question))) throw new Exception('生成失败', 9200);

        ecmsSetShowKey(static::VERIFY_KEY[$add['v']], $answer);
        // 直出图象
        if (!$imageBase64) return $imageData;

        return sprintf('data:image/%s;base64,%s', $this->getContentType(), base64_encode($imageData));
    }

    /**
     * 生成图像
     *
     * @param string $value
     * @return string
     */
    protected function imageData(string $value): string
    {
        if (!function_exists('imagettfbbox')) {
            throw new Exception('缺失"imagettfbbox"方法, 请安装FreeType library。',9200);
        }
        $image = imagecreate($this->width, $this->height);
        $ang = mt_rand(-5, 5);
        $fontpath = __DIR__ . DIRECTORY_SEPARATOR . 'font.ttf';
        $bgcolor = imagecolorallocate($image, ...$this->bgcolor);
        imagefill($image, 0, 0, $bgcolor);
        $fontcolor = imagecolorallocate($image, ...$this->fontcolor);
        $distcolor = imagecolorallocate($image, ...$this->distcolor);
        $bbox = imagettfbbox($this->fontsize, $ang, $fontpath, $value);
        $calc = $this->imagettfbboxCalc($bbox);
        imagettftext($image, $this->fontsize, $ang, $calc['x'], $calc['y'], $fontcolor, $fontpath, $value);

        // 加入干扰象素
        for($i = 0; $i < 90; $i++) {

            imagesetpixel($image, rand() % 70, rand() % 30, $distcolor);
        }

        ob_start();

        match ($this->imageType) {
            'png' => imagepng($image),
            'jpeg' => imagejpeg($image, null, 90),
            'gif' => imagegif($image),
            'wbmp' => imagewbmp($image),
            default => throw new InvalidArgumentException('不支持生成类型: ' . $this->imageType, 9200),
        };

        imagedestroy($image);

        return (string) ob_get_clean();
    }

    /**
     * 生成随机问题和答案
     *
     * @return array
     */
    protected function randomQuestionAndAnswer(): array
    {
        $num1 = rand(1, 15);
	    $num2 = rand(1, 15);
	    $symbol = $num1 > $num2 ? '-' : '+';

        return [
            $num1 . $symbol . $num2 . '=', 
            '+' === $symbol ? $num1 + $num2 : $num1 - $num2
        ];
    }
}